package com.golxen.framework.executor;

import com.golxen.utils.LogUtil;
import org.slf4j.Logger;

import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 执行统计与耗时
 */
public abstract class GeneralTask extends CancellableTask {

	private static final Map<String, AtomicInteger> taskCreateCount = new TreeMap<String, AtomicInteger>();

	private static final Map<String, AtomicInteger> taskCancelCount = new TreeMap<String, AtomicInteger>();

	private static final Map<String, AtomicInteger> taskExecuteCount = new TreeMap<String, AtomicInteger>();

	private static long lastTime = 0;

	private static final int StatOutputTime = 5 * 60 * 1000;

	public GeneralTask() {
		stat(taskCreateCount);
	}

	@Override
	public void run() {
		long startTime = System.currentTimeMillis();

		try {
			doRun();
		} catch (Throwable e) {
		    LogUtil.COMMON.error(e.getMessage(), e);
		} finally {
			long endTime = System.currentTimeMillis();
			long costTime = endTime - startTime;

			if (costTime > 2000) {
			    LogUtil.COMMON.warn("GeneralTask [{}], cost [{}] millis", getTaskName(), costTime);
			}

			stat(taskExecuteCount);
		}
	}

	public abstract void doRun();

	public String getTaskName() {
		return this.getClass().getName();
	}

	@Override
	public boolean cancel(boolean mayInterruptIfRunning) {
		stat(taskCancelCount);

		return super.cancel(mayInterruptIfRunning);
	}

	@Override
	public String toString() {

		return this.getClass().getName();
	}

	public void stat(Map<String, AtomicInteger> countMap) {
		synchronized (countMap) {
			String key = this.getClass().getSimpleName();
			AtomicInteger count = countMap.get(key);
			if (count == null) {
				count = new AtomicInteger(0);
				countMap.put(key, count);
			}

			count.incrementAndGet();
		}

		long costTime = System.currentTimeMillis() - lastTime;
		if (costTime >= StatOutputTime) {
		    LogUtil.COMMON.info("Create:" + taskCreateCount);
		    LogUtil.COMMON.info("Cancel:" + taskCancelCount);
		    LogUtil.COMMON.info("Execute" + taskExecuteCount);
			lastTime = System.currentTimeMillis();
		}
	}

	public static Logger getLOGGER() {
		return LogUtil.COMMON;
	}
}
